package com.e3.template.tgf;

import java.util.List;

import com.e3.web.core.client.EditorListener;
import com.e3.web.core.client.GXTHelper;
import com.e3.web.core.client.GridListener;
import com.e3.web.core.client.GwtAsyncCallback;
import com.e3.web.core.client.QueryListener;
import com.e3.web.core.model.SuperModel;
import com.e3.web.core.model.SuperQC;
import com.e3.web.widget.client.BaseAction;
import com.e3.web.widget.client.MyButton;
import com.e3.web.widget.client.MyMenu;
import com.e3.web.widget.client.MyMenuItem;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.rpc.AsyncCallback;

public abstract class SuperGFUI<D extends SuperModel> extends LayoutContainer implements GridListener<D>,EditorListener<D>,QueryListener<D> {

	private SelectionListener<ButtonEvent> btnSelectListener = new SelectionListener<ButtonEvent>() {
		@Override
		public void componentSelected(ButtonEvent ce) {
			MyButton item = (MyButton)ce.getSource();
			onBtnMnuEvent(item.getAction());
		}
	};
	
	private SelectionListener<MenuEvent> mnuSelectListener = new SelectionListener<MenuEvent>() {
		@Override
		public void componentSelected(MenuEvent ce) {
			MyMenuItem item = (MyMenuItem)ce.getItem();
			BaseAction action = item.getAction();
			MyMenu menu = (MyMenu)item.getParentMenu();
			action.setSource(menu.getMenuOwner());
			onBtnMnuEvent(item.getAction());
		}
	};
	
	private Listener<MessageBoxEvent> msgBoxListener = new Listener<MessageBoxEvent>(){
		public void handleEvent(MessageBoxEvent be) {
			Button btn = be.getButtonClicked();
			onMessageBoxButton(btn);
		}
	};
	
	private TGFMessages TGFMESSAGES = TGFMessages.INSTANCE;
	
	private ToolBar toolbar = new ToolBar();
	
	private ContentPanel rightContentPanel = new ContentPanel(new BorderLayout());
	
	private D gridSelectedModel;

	private TGFFormPanel<D> formPanel;
	private TGFGridPanel<D> gridPanel;
	
	private TGFQueryDialog<D> queryDialog;
	private TGFEditorDialog<D> editorDialog;
	
//	private MyButton queryButton = new MyButton(TGFStateMachine.QUERY_ACTION);
//	private MyButton newButton = new MyButton(TGFStateMachine.NEW_ACTION);
//	private MyButton modifyButton = new MyButton(TGFStateMachine.MODIFY_ACTION);
//	private MyButton deleteButton = new MyButton(TGFStateMachine.DELETE_ACTION);

//	@Override
//	protected void onRender(Element parent, int index) {
//		super.onRender(parent, index);
//		this.setLayout(new FitLayout());
//
//		BorderLayoutData bld = new BorderLayoutData(LayoutRegion.NORTH);
//		bld.setSplit(true);
//		bld.setMargins(new Margins(0,2,0,0));
//		rightContentPanel.add(getGridPanel(),bld);
//		
//		bld = new BorderLayoutData(LayoutRegion.CENTER);
//		rightContentPanel.add(getFormPanel(),bld);
//		getFormPanel().setFormReadonly(true);
//		
//		
//		initToolBar();
//		rightContentPanel.setTopComponent(toolbar);
//		rightContentPanel.setHeaderVisible(false);
//
//		this.add(rightContentPanel);
//	}
	
	public SuperGFUI(){
		TGFStateMachine.init(getCurrentLocalName());
	}
	
	protected void initToolBar() {
		MyButton[] buttons = getToolButtons();
		for (MyButton myButton : buttons) {
			myButton.addSelectionListener(btnSelectListener);
			toolbar.add(myButton);			
		}
	}
	
	public ContentPanel getRightContentPanel() {
		return rightContentPanel;
	}
	
	public ToolBar getToolbar() {
		return toolbar;
	}
	
	public TGFFormPanel<D> getFormPanel() {
		if(formPanel == null){
			formPanel = createFormPanel();
			formPanel.setFormReadonly(true);
		}
		return formPanel;
	}

	public TGFGridPanel<D> getGridPanel() {
		if(gridPanel == null){
			gridPanel = createGridPanel();
			gridPanel.addGridListener(this);
			gridPanel.setGridContextMenu(getGridContextMenu());
		}
		return gridPanel;
	}

	protected TGFEditorDialog<D> getEditorDialog() {
		if(editorDialog == null){
			editorDialog = createEditorDialog();
			editorDialog.addEditorListener(this);
		}
		return editorDialog;
	}

	protected TGFQueryDialog<D> getQueryDialog() {
		if(queryDialog == null){
			queryDialog = createQueryDialog();
			queryDialog.setLocalName(getCurrentLocalName());
			queryDialog.addQueryListener(this);
		}
		return queryDialog;
	}
	
	protected Menu getGridContextMenu(){
		MyMenu menu = new MyMenu();
		
		BaseAction[] actions = getGridContextMenuActions();
		for (BaseAction baseAction : actions) {
			MyMenuItem item = new MyMenuItem(baseAction);
			item.addSelectionListener(getMnuSelectListener());
			menu.add(item);
		}
		
		return menu;
		
	}
	
	protected BaseAction[] getGridContextMenuActions(){
		return new BaseAction[]{
				TGFStateMachine.NEW_CHILD_ACTION,TGFStateMachine.NEW_ACTION
				,TGFStateMachine.MODIFY_ACTION,TGFStateMachine.DELETE_ACTION}; 
	}

	protected MyButton[] getToolButtons(){
		BaseAction[] actions = getToolButtonActions();
		MyButton[] buttons = new MyButton[actions.length];
		for(int i=0;i<actions.length;i++){
			buttons[i]=new MyButton(actions[i]);
		}
		return buttons;
	}

	protected BaseAction[] getToolButtonActions(){
		return new BaseAction[]{TGFStateMachine.QUERY_ACTION,TGFStateMachine.NEW_ACTION
				,TGFStateMachine.MODIFY_ACTION,TGFStateMachine.DELETE_ACTION};
	}
	
	protected void onMessageBoxButton(Button btn) {
		if("yes".equals(btn.getItemId())){
			GXTHelper.maskDelete(this);
			final List<D> models = getCurrentSelectedModels();
			executeDeleteService(models,getDeleteAsyncCallback(models));
		}
	}

	protected void onBtnMnuEvent(BaseAction action) {
		if(action == TGFStateMachine.QUERY_ACTION){
			onQuery();
		}
		else if(action == TGFStateMachine.NEW_ACTION){
			onNew();
		}
		else if(action == TGFStateMachine.MODIFY_ACTION){
			onModify();
		}
		else if(action == TGFStateMachine.DELETE_ACTION){
			onDelete();
		}
	}

	protected void onDelete() {
		List<D> models = getCurrentSelectedModels();
		if(models == null||models.size()==0){
			MessageBox.alert(TGFMESSAGES.msgbox_alert_title(), TGFMESSAGES.msg_delete_info(getCurrentLocalName()), null);
			return;
		}
		String localName = getCurrentLocalName();
		String msgs = getDeletedDetailInfo(models);
		MessageBox.confirm(TGFMESSAGES.msgbox_confirm_delete_title(), TGFMESSAGES.msg_delete_confirm(localName, msgs), msgBoxListener);
	}

	protected void onModify() {
		List<D> models = getCurrentSelectedModels();
		if(models == null || models.size()==0){
			MessageBox.alert(TGFMESSAGES.msgbox_alert_title(),TGFMESSAGES.msg_modify_info(getCurrentLocalName()), null);
			return;
		}
		getEditorDialog().showDialog(models.get(0),getCurrentLocalName(),false);

	}

	protected void onNew() {
		D model = createModelInstance();
		getEditorDialog().showDialog(model,getCurrentLocalName(),true);		
	}

	protected void onQuery() {
		getQueryDialog().setVisible(true);
	}

	public void onGridSelectionChanged(D model) {
		gridSelectedModel =  model;
		getFormPanel().setFormValue(model);
	}

	public void onGridRowDoubClicked(D model) {
		onModify();
	}
	
	public void onQuerySuccessed(SuperQC qc,List<D> results) {
		if(getGridPanel() instanceof TGFPagingGridPanel){
			((TGFPagingGridPanel<D>)getGridPanel()).refreshPaging(qc);
		}
		else{
			getGridPanel().setGridValues(results);		
		}		
	}

	public SelectionListener<MenuEvent> getMnuSelectListener() {
		return mnuSelectListener;
	}

	public Listener<MessageBoxEvent> getMsgBoxListener() {
		return msgBoxListener;
	}

	public D getGridSelectedModel(){
		return gridSelectedModel;
	}

	public SelectionListener<ButtonEvent> getBtnSelectListener() {
		return btnSelectListener;
	}

	protected String getDeletedDetailInfo(List<D> models){
		StringBuffer msgs = new StringBuffer();
		for (D d : models) {
			msgs.append(d.toString()+",");
		}
		return msgs.substring(0,msgs.length()-1);
	}
	
	protected AsyncCallback<Void> getDeleteAsyncCallback(final List<D> models) {
		return new GwtAsyncCallback<Void>(this) {
			@Override
			public void doSuccess(Void result) {
				onDeleteSuccess(models);
			}
		};
	}
	
	public abstract void onEditSuccess(D model);
	
	protected abstract void onDeleteSuccess(List<D> models);
	
	protected abstract List<D> getCurrentSelectedModels();

	protected abstract TGFFormPanel<D> createFormPanel();
	
	protected abstract TGFGridPanel<D> createGridPanel();
	
	protected abstract TGFQueryDialog<D> createQueryDialog();
	
	protected abstract TGFEditorDialog<D> createEditorDialog();
	
	protected abstract void executeDeleteService(List<D> models,AsyncCallback<Void> callback);
	
	protected abstract String getCurrentLocalName();
	
	protected abstract D createModelInstance();
}
